; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -mattr=+xtheadmempair -verify-machineinstrs < %s \
; RUN:   | FileCheck %s -check-prefix=RV32XTHEADMEMPAIR
; RUN: llc -mtriple=riscv64 -mattr=+xtheadmempair -verify-machineinstrs < %s \
; RUN:   | FileCheck %s -check-prefix=RV64XTHEADMEMPAIR

define i64 @lwd(i32* %a) {
; RV32XTHEADMEMPAIR-LABEL: lwd:
; RV32XTHEADMEMPAIR:       # %bb.0:
; RV32XTHEADMEMPAIR-NEXT:    th.lwd a1, a2, (a0), 2, 3
; RV32XTHEADMEMPAIR-NEXT:    srai a3, a1, 31
; RV32XTHEADMEMPAIR-NEXT:    srai a4, a2, 31
; RV32XTHEADMEMPAIR-NEXT:    add a0, a1, a2
; RV32XTHEADMEMPAIR-NEXT:    sltu a1, a0, a1
; RV32XTHEADMEMPAIR-NEXT:    add a3, a3, a4
; RV32XTHEADMEMPAIR-NEXT:    add a1, a3, a1
; RV32XTHEADMEMPAIR-NEXT:    ret
;
; RV64XTHEADMEMPAIR-LABEL: lwd:
; RV64XTHEADMEMPAIR:       # %bb.0:
; RV64XTHEADMEMPAIR-NEXT:    th.lwd a1, a2, (a0), 2, 3
; RV64XTHEADMEMPAIR-NEXT:    add a0, a1, a2
; RV64XTHEADMEMPAIR-NEXT:    ret
  %1 = getelementptr i32, i32* %a, i64 4
  %2 = load i32, i32* %1, align 4
  %3 = getelementptr i32, i32* %a, i64 5
  %4 = load i32, i32* %3, align 4
  %5 = sext i32 %2 to i64
  %6 = sext i32 %4 to i64
  %7 = add i64 %5, %6
  ret i64 %7
}

define i64 @lwud(i32* %a) {
; RV32XTHEADMEMPAIR-LABEL: lwud:
; RV32XTHEADMEMPAIR:       # %bb.0:
; RV32XTHEADMEMPAIR-NEXT:    th.lwd a1, a2, (a0), 2, 3
; RV32XTHEADMEMPAIR-NEXT:    add a0, a1, a2
; RV32XTHEADMEMPAIR-NEXT:    sltu a1, a0, a1
; RV32XTHEADMEMPAIR-NEXT:    ret
;
; RV64XTHEADMEMPAIR-LABEL: lwud:
; RV64XTHEADMEMPAIR:       # %bb.0:
; RV64XTHEADMEMPAIR-NEXT:    th.lwud a1, a2, (a0), 2, 3
; RV64XTHEADMEMPAIR-NEXT:    add a0, a1, a2
; RV64XTHEADMEMPAIR-NEXT:    ret
  %1 = getelementptr i32, i32* %a, i64 4
  %2 = load i32, i32* %1, align 4
  %3 = getelementptr i32, i32* %a, i64 5
  %4 = load i32, i32* %3, align 4
  %5 = zext i32 %2 to i64
  %6 = zext i32 %4 to i64
  %7 = add i64 %5, %6
  ret i64 %7
}

define i64 @ldd(i64* %a) {
; RV32XTHEADMEMPAIR-LABEL: ldd:
; RV32XTHEADMEMPAIR:       # %bb.0:
; RV32XTHEADMEMPAIR-NEXT:    lw a1, 32(a0)
; RV32XTHEADMEMPAIR-NEXT:    lw a2, 36(a0)
; RV32XTHEADMEMPAIR-NEXT:    lw a3, 44(a0)
; RV32XTHEADMEMPAIR-NEXT:    lw a0, 40(a0)
; RV32XTHEADMEMPAIR-NEXT:    add a2, a2, a3
; RV32XTHEADMEMPAIR-NEXT:    add a0, a1, a0
; RV32XTHEADMEMPAIR-NEXT:    sltu a1, a0, a1
; RV32XTHEADMEMPAIR-NEXT:    add a1, a2, a1
; RV32XTHEADMEMPAIR-NEXT:    ret
;
; RV64XTHEADMEMPAIR-LABEL: ldd:
; RV64XTHEADMEMPAIR:       # %bb.0:
; RV64XTHEADMEMPAIR-NEXT:    th.ldd a1, a2, (a0), 2, 4
; RV64XTHEADMEMPAIR-NEXT:    add a0, a1, a2
; RV64XTHEADMEMPAIR-NEXT:    ret
  %1 = getelementptr i64, i64* %a, i64 4
  %2 = load i64, i64* %1, align 8
  %3 = getelementptr i64, i64* %a, i64 5
  %4 = load i64, i64* %3, align 8
  %5 = add i64 %2, %4
  ret i64 %5
}

define i64 @lwd_0(i32* %a) {
; RV32XTHEADMEMPAIR-LABEL: lwd_0:
; RV32XTHEADMEMPAIR:       # %bb.0:
; RV32XTHEADMEMPAIR-NEXT:    th.lwd a1, a2, (a0), 0, 3
; RV32XTHEADMEMPAIR-NEXT:    srai a3, a1, 31
; RV32XTHEADMEMPAIR-NEXT:    srai a4, a2, 31
; RV32XTHEADMEMPAIR-NEXT:    add a0, a1, a2
; RV32XTHEADMEMPAIR-NEXT:    sltu a1, a0, a1
; RV32XTHEADMEMPAIR-NEXT:    add a3, a3, a4
; RV32XTHEADMEMPAIR-NEXT:    add a1, a3, a1
; RV32XTHEADMEMPAIR-NEXT:    ret
;
; RV64XTHEADMEMPAIR-LABEL: lwd_0:
; RV64XTHEADMEMPAIR:       # %bb.0:
; RV64XTHEADMEMPAIR-NEXT:    th.lwd a1, a2, (a0), 0, 3
; RV64XTHEADMEMPAIR-NEXT:    add a0, a1, a2
; RV64XTHEADMEMPAIR-NEXT:    ret
  %1 = getelementptr i32, i32* %a, i64 0
  %2 = load i32, i32* %1, align 4
  %3 = getelementptr i32, i32* %a, i64 1
  %4 = load i32, i32* %3, align 4
  %5 = sext i32 %2 to i64
  %6 = sext i32 %4 to i64
  %7 = add i64 %5, %6
  ret i64 %7
}

define i64 @lwud_0(i32* %a) {
; RV32XTHEADMEMPAIR-LABEL: lwud_0:
; RV32XTHEADMEMPAIR:       # %bb.0:
; RV32XTHEADMEMPAIR-NEXT:    th.lwd a1, a2, (a0), 0, 3
; RV32XTHEADMEMPAIR-NEXT:    add a0, a1, a2
; RV32XTHEADMEMPAIR-NEXT:    sltu a1, a0, a1
; RV32XTHEADMEMPAIR-NEXT:    ret
;
; RV64XTHEADMEMPAIR-LABEL: lwud_0:
; RV64XTHEADMEMPAIR:       # %bb.0:
; RV64XTHEADMEMPAIR-NEXT:    th.lwud a1, a2, (a0), 0, 3
; RV64XTHEADMEMPAIR-NEXT:    add a0, a1, a2
; RV64XTHEADMEMPAIR-NEXT:    ret
  %1 = getelementptr i32, i32* %a, i64 0
  %2 = load i32, i32* %1, align 4
  %3 = getelementptr i32, i32* %a, i64 1
  %4 = load i32, i32* %3, align 4
  %5 = zext i32 %2 to i64
  %6 = zext i32 %4 to i64
  %7 = add i64 %5, %6
  ret i64 %7
}

define i64 @ldd_0(i64* %a) {
; RV32XTHEADMEMPAIR-LABEL: ldd_0:
; RV32XTHEADMEMPAIR:       # %bb.0:
; RV32XTHEADMEMPAIR-NEXT:    th.lwd a1, a2, (a0), 0, 3
; RV32XTHEADMEMPAIR-NEXT:    th.lwd a3, a4, (a0), 1, 3
; RV32XTHEADMEMPAIR-NEXT:    add a2, a2, a4
; RV32XTHEADMEMPAIR-NEXT:    add a0, a1, a3
; RV32XTHEADMEMPAIR-NEXT:    sltu a1, a0, a1
; RV32XTHEADMEMPAIR-NEXT:    add a1, a2, a1
; RV32XTHEADMEMPAIR-NEXT:    ret
;
; RV64XTHEADMEMPAIR-LABEL: ldd_0:
; RV64XTHEADMEMPAIR:       # %bb.0:
; RV64XTHEADMEMPAIR-NEXT:    th.ldd a1, a2, (a0), 0, 4
; RV64XTHEADMEMPAIR-NEXT:    add a0, a1, a2
; RV64XTHEADMEMPAIR-NEXT:    ret
  %1 = getelementptr i64, i64* %a, i64 0
  %2 = load i64, i64* %1, align 8
  %3 = getelementptr i64, i64* %a, i64 1
  %4 = load i64, i64* %3, align 8
  %5 = add i64 %2, %4
  ret i64 %5
}

define void @swd(i32* %a, i32 %b, i32%c) {
; RV32XTHEADMEMPAIR-LABEL: swd:
; RV32XTHEADMEMPAIR:       # %bb.0:
; RV32XTHEADMEMPAIR-NEXT:    th.swd a1, a2, (a0), 2, 3
; RV32XTHEADMEMPAIR-NEXT:    ret
;
; RV64XTHEADMEMPAIR-LABEL: swd:
; RV64XTHEADMEMPAIR:       # %bb.0:
; RV64XTHEADMEMPAIR-NEXT:    th.swd a1, a2, (a0), 2, 3
; RV64XTHEADMEMPAIR-NEXT:    ret
  %1 = getelementptr i32, i32* %a, i64 4
  store i32 %b, i32* %1, align 4
  %2 = getelementptr i32, i32* %a, i64 5
  store i32 %c, i32* %2, align 4
  ret void
}

define void @sdd(i64* %a, i64 %b, i64%c) {
; RV32XTHEADMEMPAIR-LABEL: sdd:
; RV32XTHEADMEMPAIR:       # %bb.0:
; RV32XTHEADMEMPAIR-NEXT:    sw a2, 36(a0)
; RV32XTHEADMEMPAIR-NEXT:    sw a1, 32(a0)
; RV32XTHEADMEMPAIR-NEXT:    sw a4, 44(a0)
; RV32XTHEADMEMPAIR-NEXT:    sw a3, 40(a0)
; RV32XTHEADMEMPAIR-NEXT:    ret
;
; RV64XTHEADMEMPAIR-LABEL: sdd:
; RV64XTHEADMEMPAIR:       # %bb.0:
; RV64XTHEADMEMPAIR-NEXT:    th.sdd a1, a2, (a0), 2, 4
; RV64XTHEADMEMPAIR-NEXT:    ret
  %1 = getelementptr i64, i64* %a, i64 4
  store i64 %b, i64* %1, align 8
  %2 = getelementptr i64, i64* %a, i64 5
  store i64 %c, i64* %2, align 8
  ret void
}

define void @swd_0(i32* %a, i32 %b, i32%c) {
; RV32XTHEADMEMPAIR-LABEL: swd_0:
; RV32XTHEADMEMPAIR:       # %bb.0:
; RV32XTHEADMEMPAIR-NEXT:    th.swd a1, a2, (a0), 0, 3
; RV32XTHEADMEMPAIR-NEXT:    ret
;
; RV64XTHEADMEMPAIR-LABEL: swd_0:
; RV64XTHEADMEMPAIR:       # %bb.0:
; RV64XTHEADMEMPAIR-NEXT:    th.swd a1, a2, (a0), 0, 3
; RV64XTHEADMEMPAIR-NEXT:    ret
  %1 = getelementptr i32, i32* %a, i64 0
  store i32 %b, i32* %1, align 4
  %2 = getelementptr i32, i32* %a, i64 1
  store i32 %c, i32* %2, align 4
  ret void
}

define void @sdd_0(i64* %a, i64 %b, i64%c) {
; RV32XTHEADMEMPAIR-LABEL: sdd_0:
; RV32XTHEADMEMPAIR:       # %bb.0:
; RV32XTHEADMEMPAIR-NEXT:    th.swd a1, a2, (a0), 0, 3
; RV32XTHEADMEMPAIR-NEXT:    th.swd a3, a4, (a0), 1, 3
; RV32XTHEADMEMPAIR-NEXT:    ret
;
; RV64XTHEADMEMPAIR-LABEL: sdd_0:
; RV64XTHEADMEMPAIR:       # %bb.0:
; RV64XTHEADMEMPAIR-NEXT:    th.sdd a1, a2, (a0), 0, 4
; RV64XTHEADMEMPAIR-NEXT:    ret
  %1 = getelementptr i64, i64* %a, i64 0
  store i64 %b, i64* %1, align 8
  %2 = getelementptr i64, i64* %a, i64 1
  store i64 %c, i64* %2, align 8
  ret void
}

define i64 @ld64(i64* %a) {
; RV32XTHEADMEMPAIR-LABEL: ld64:
; RV32XTHEADMEMPAIR:       # %bb.0:
; RV32XTHEADMEMPAIR-NEXT:    th.lwd a2, a1, (a0), 0, 3
; RV32XTHEADMEMPAIR-NEXT:    mv a0, a2
; RV32XTHEADMEMPAIR-NEXT:    ret
;
; RV64XTHEADMEMPAIR-LABEL: ld64:
; RV64XTHEADMEMPAIR:       # %bb.0:
; RV64XTHEADMEMPAIR-NEXT:    ld a0, 0(a0)
; RV64XTHEADMEMPAIR-NEXT:    ret
  %1 = getelementptr i64, i64* %a, i64 0
  %2 = load i64, i64* %1, align 8
  ret i64 %2
}

define i128 @ld128(i128* %a) {
; RV32XTHEADMEMPAIR-LABEL: ld128:
; RV32XTHEADMEMPAIR:       # %bb.0:
; RV32XTHEADMEMPAIR-NEXT:    th.lwd a2, a3, (a1), 1, 3
; RV32XTHEADMEMPAIR-NEXT:    th.lwd a4, a5, (a1), 0, 3
; RV32XTHEADMEMPAIR-NEXT:    th.swd a2, a3, (a0), 1, 3
; RV32XTHEADMEMPAIR-NEXT:    th.swd a4, a5, (a0), 0, 3
; RV32XTHEADMEMPAIR-NEXT:    ret
;
; RV64XTHEADMEMPAIR-LABEL: ld128:
; RV64XTHEADMEMPAIR:       # %bb.0:
; RV64XTHEADMEMPAIR-NEXT:    th.ldd a2, a1, (a0), 0, 4
; RV64XTHEADMEMPAIR-NEXT:    mv a0, a2
; RV64XTHEADMEMPAIR-NEXT:    ret
  %1 = getelementptr i128, i128* %a, i64 0
  %2 = load i128, i128* %1, align 8
  ret i128 %2
}

define void @sd64(i64* %a, i64 %b) {
; RV32XTHEADMEMPAIR-LABEL: sd64:
; RV32XTHEADMEMPAIR:       # %bb.0:
; RV32XTHEADMEMPAIR-NEXT:    th.swd a1, a2, (a0), 0, 3
; RV32XTHEADMEMPAIR-NEXT:    ret
;
; RV64XTHEADMEMPAIR-LABEL: sd64:
; RV64XTHEADMEMPAIR:       # %bb.0:
; RV64XTHEADMEMPAIR-NEXT:    sd a1, 0(a0)
; RV64XTHEADMEMPAIR-NEXT:    ret
  %1 = getelementptr i64, i64* %a, i64 0
  store i64 %b, i64* %1, align 8
  ret void
}

define void @sd128(i128* %a, i128 %b) {
; RV32XTHEADMEMPAIR-LABEL: sd128:
; RV32XTHEADMEMPAIR:       # %bb.0:
; RV32XTHEADMEMPAIR-NEXT:    th.lwd a2, a3, (a1), 1, 3
; RV32XTHEADMEMPAIR-NEXT:    th.lwd a4, a5, (a1), 0, 3
; RV32XTHEADMEMPAIR-NEXT:    th.swd a2, a3, (a0), 1, 3
; RV32XTHEADMEMPAIR-NEXT:    th.swd a4, a5, (a0), 0, 3
; RV32XTHEADMEMPAIR-NEXT:    ret
;
; RV64XTHEADMEMPAIR-LABEL: sd128:
; RV64XTHEADMEMPAIR:       # %bb.0:
; RV64XTHEADMEMPAIR-NEXT:    th.sdd a1, a2, (a0), 0, 4
; RV64XTHEADMEMPAIR-NEXT:    ret
  %1 = getelementptr i128, i128* %a, i64 0
  store i128 %b, i128* %1, align 8
  ret void
}

define i32 @lh(i16* %a) {
; RV32XTHEADMEMPAIR-LABEL: lh:
; RV32XTHEADMEMPAIR:       # %bb.0:
; RV32XTHEADMEMPAIR-NEXT:    lh a1, 0(a0)
; RV32XTHEADMEMPAIR-NEXT:    lh a0, 2(a0)
; RV32XTHEADMEMPAIR-NEXT:    add a0, a1, a0
; RV32XTHEADMEMPAIR-NEXT:    ret
;
; RV64XTHEADMEMPAIR-LABEL: lh:
; RV64XTHEADMEMPAIR:       # %bb.0:
; RV64XTHEADMEMPAIR-NEXT:    lh a1, 0(a0)
; RV64XTHEADMEMPAIR-NEXT:    lh a0, 2(a0)
; RV64XTHEADMEMPAIR-NEXT:    add a0, a1, a0
; RV64XTHEADMEMPAIR-NEXT:    ret
  %1 = getelementptr i16, i16* %a, i64 0
  %2 = load i16, i16* %1, align 4
  %3 = getelementptr i16, i16* %a, i64 1
  %4 = load i16, i16* %3, align 4
  %5 = sext i16 %2 to i32
  %6 = sext i16 %4 to i32
  %7 = add i32 %5, %6
  ret i32 %7
}

define i32 @lb(i8* %a) {
; RV32XTHEADMEMPAIR-LABEL: lb:
; RV32XTHEADMEMPAIR:       # %bb.0:
; RV32XTHEADMEMPAIR-NEXT:    lb a1, 0(a0)
; RV32XTHEADMEMPAIR-NEXT:    lb a0, 1(a0)
; RV32XTHEADMEMPAIR-NEXT:    add a0, a1, a0
; RV32XTHEADMEMPAIR-NEXT:    ret
;
; RV64XTHEADMEMPAIR-LABEL: lb:
; RV64XTHEADMEMPAIR:       # %bb.0:
; RV64XTHEADMEMPAIR-NEXT:    lb a1, 0(a0)
; RV64XTHEADMEMPAIR-NEXT:    lb a0, 1(a0)
; RV64XTHEADMEMPAIR-NEXT:    add a0, a1, a0
; RV64XTHEADMEMPAIR-NEXT:    ret
  %1 = getelementptr i8, i8* %a, i64 0
  %2 = load i8, i8* %1, align 4
  %3 = getelementptr i8, i8* %a, i64 1
  %4 = load i8, i8* %3, align 4
  %5 = sext i8 %2 to i32
  %6 = sext i8 %4 to i32
  %7 = add i32 %5, %6
  ret i32 %7
}
